"
" Install "https://github.com/junegunn/vim-plug", 
" then run :PlugInstall
"          :CocInstall coc-clangd coc-json coc-sumneko-lua coc-go
"          npm i -g bash-language-server

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" plug list
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
    Plug 'honza/vim-snippets'
    Plug 'mhinz/vim-startify'
    Plug 'rhysd/clever-f.vim'
    Plug 'octol/vim-cpp-enhanced-highlight'
    Plug 'tpope/vim-commentary'
    Plug 'jiangmiao/auto-pairs'
    Plug 'catppuccin/vim'
    Plug 'preservim/nerdtree', {'on': 'NERDTreeToggle'} 
    Plug 'vim-airline/vim-airline'
    Plug 'vim-airline/vim-airline-themes'
    Plug 'ryanoasis/vim-devicons'
    Plug 'airblade/vim-gitgutter'
    Plug 'Yggdroot/indentLine'
    Plug 'machakann/vim-highlightedyank' 
    Plug 'markonm/traces.vim' " live substitute
    Plug 'voldikss/vim-floaterm'
    Plug 'RRethy/vim-illuminate' " curorword highlight
    Plug 'bfrg/vim-qf-diagnostics'
call plug#end()

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" base config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let mapleader = "\<space>"

set nocompatible         " set not compatible with vi
set noeb                 " turn off error syntax prompts
syntax enable            " highlight enable
syntax on                " highlight auto
filetype on              " set file type detection
filetype plugin on       " set load plugin by file type
filetype indent on       " intelligent indent for different languages
set termguicolors        " set real color
set t_Co=256             " open 256 color
set belloff=all vb t_vb= " set no bell
set cmdheight=1          " set command height
set showcmd              " show select line nums in visual
set textwidth=0          " close auto enter
set ruler                " cursor position displayed
set laststatus=1         " show status
set number               " show line number
set relativenumber       " show relativenumber
set cursorline           " highlight current line
set whichwrap+=<,>,h,l   " set the cursor key across rows
set ttimeoutlen=0        " set <ESC> response time
set virtualedit=block    " allows the cursor appear after last character
set noshowmode           " disable bottom mode displayed 'insert'
set hidden               " allows toggle buffers in unsaved
set matchpairs+=<:>      " make % can jump <>
set background=dark      " set background color
set title                " update the title of terminal
" set jumpoptions=stack    " save jump records in form of stack
set undofile             " enable persistent undo log
if has('win32')
  let undodir = '~/vimfiles/undodir'
else
  let undodir = '~/.vim/undodir'
endif
if !isdirectory(expand(undodir))
  call mkdir(expand(undodir), 'p')
endif
let &undodir = expand(undodir)

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" colorscheme config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" colorscheme slate
colorscheme catppuccin_mocha

highlight Statement cterm=none gui=none
highlight Constant cterm=none gui=none
highlight PreProc cterm=none gui=none
highlight Type cterm=none gui=none
highlight Special cterm=none gui=none
highlight Underlined cterm=none gui=none
highlight String cterm=none gui=none
highlight Function cterm=none gui=none

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" code indent and typesetting config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set autoindent           " set auto indent
set cindent              " set indent by c/cpp
set cinoptions=(s,:0,l1,g0,t0,N-s,E-s " set c/cpp indent way
set smartindent          " smart choose indent way
set expandtab            " use space to replace tab
set tabstop=4            " number of spaces used by tabs when editing
set shiftwidth=4         " number of spaces tab occupies when formatting
set softtabstop=4        " set 4 spaces as tabs
set smarttab             " use tabs at the beginning of lines and segments
set nowrap               " disable divide a line to two
set backspace=indent,eol,start " let backspace work normally
set sidescroll=8        " sets the number of characters to scroll to the right
set nofoldenable         " disables folding code
set list lcs=tab:¦\      " default show indent line
set sidescrolloff=5      " set curor line to right
set scrolloff=8          " set cursor line to bottom
" set mouse=a              " enable the mouse
set clipboard=unnamed    " Sync clipboard contents to system clipboard
set signcolumn=yes       " Always show the signcolumn

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" code inside completion config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set wildmenu             " vim itself named line pattern intelligent completion
set completeopt-=preview " completion window is not displayed when completed, only list is displayed

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" search config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set hlsearch             " highlight search results
set incsearch            " turn on real-time search
set ignorecase           " search is not case sensitive
set smartcase            " search smart match case
set showmatch
set matchtime=5

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" cache config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set nobackup             " set no back up
set noswapfile           " disable create temp file
set autoread             " if file change by others,load it auto
set autowrite            " set auto save
set confirm              " if quit without save,make confirm

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" encode config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set langmenu=zh_CN.UTF-8 " set langmenu encode utf-8
set helplang=cn          " set helplang Chinese
set termencoding=utf-8   " set term encode
set encoding=utf8        " set encode
set fileencodings=utf8,ucs-bom,gbk,cp936,gb2312,gb18030 " set detect encode of file
" set fileformat=unix fileformats=unix " let vim select the style of file eof, such as \n \r\n

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" gvim/macvim config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
if has("gui_running")
    set lines=1000 co=1000
    set guifont=SF\ Mono:h11  " set fonts in gvim
	set guioptions-=m         " hide the menu bar
	set guioptions-=T         " hide tool bar
	set guioptions-=L         " hide left scroll bar
	set guioptions-=r         " hide right scroll bar
	set guioptions-=b         " hide bottom scroll bar
	set showtabline=0         " hide tab bar
    set guicursor=a:blinkon0  " set cursor stop blink

    if has('win32') || has('unix')
      nnoremap <c-w>      :w<cr>:confirm qa<cr>
      inoremap <c-w> <Esc>:w<cr>:confirm qa<cr>
      vnoremap <c-w> <Esc>:w<cr>:confirm qa<cr>
    endif
    if has('mac') || has('macunix')
      " MacVim 支持 <D-w> 表示 Command+W
      nnoremap <D-w> :confirm qa<cr>
    endif
endif

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" keymaps config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" cancel highlight
nnoremap <leader>nh :nohl<cr>
" reload .vimrc
nnoremap <leader>s :source $MYVIMRC<cr>
" install and clean plug
nnoremap <leader>i :PlugInstall<cr>
nnoremap <leader>c :PlugClean<cr>
" insert model to move cursor
imap <c-h> <left>
imap <c-j> <down>
imap <c-k> <up>
imap <c-l> <right>
" toggle buffer
nnoremap <silent>H :bp<bar>if &bt!=''<bar>bp<bar>endif<cr>
nnoremap <silent>L :bn<bar>if &bt!=''<bar>bn<bar>endif<cr>
" change window width
nnoremap <c-up>    <c-w>+
nnoremap <c-down>  <c-w>-
nnoremap <c-left>  <c-w><
nnoremap <c-right> <c-w>>
" toggle window
nnoremap <c-k> <c-w>k
nnoremap <c-j> <c-w>j
nnoremap <c-h> <c-w>h
nnoremap <c-l> <c-w>l+
" open or close buffer 
nnoremap <leader>b :buffers<cr>:b<space>
nnoremap <leader>x :bdelete<cr>
" let ctrl-d ctrl-u move more smoothly or c-e c-y
nnoremap <c-d> 3<c-n> 
nnoremap <c-u> 3<c-p> 

" support when open file jump to the position of last open 
if has("autocmd")
  augroup vimrcEx
    autocmd!
    autocmd BufReadPost *
          \ if line("'\"") > 1 && line("'\"") <= line("$") |
          \   exe "normal! g`\"" |
          \ endif
  augroup END
endif

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" plug config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"
" ==== vim-airline/vim-airline ====
"
" let g:airline_theme='tomorrow'
let g:airline_theme= "catppuccin_mocha"
let g:airline_powerline_fonts = 1
let g:airline_extensions = ['tabline' , 'coc', 'branch']
let g:airline_left_sep = ''
let g:airline_left_alt_sep = ''
let g:airline_right_sep = ''
let g:airline_right_alt_sep = ''
let g:airline#extensions#tabline#enabled = 1

"
" junegunn/fzf 
"
nnoremap <leader>f :FZF<cr>

"
" ==== preservim/nerdtree ====
"
nnoremap <leader>e :NERDTreeToggle<cr>
let g:NERDTreeFileExtensionHighlightFullName = 1
let g:NERDTreeExactMatchHighlightFullName = 1
let g:NERDTreePatternMatchHighlightFullName = 1
let g:NERDTreeHighlightFolders = 1
let g:NERDTreeHighlightFoldersFullName = 1
let g:NERDTreeDirArrowExpandable=''
let g:NERDTreeDirArrowCollapsible='▼'
let g:NERDTreeWinSize=28

augroup NerdTree
	autocmd!
	autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | :bn | endif " 当NERDTree为剩下的唯一窗口时自动关闭
augroup END

"
" ==== jiangmiao/auto-pairs ====
"
let g:AutoPairsMapCh = 0
let g:AutoPairsMapSpace = 0

"
" === octol/vim-cpp-enhanced-highlight ===
"
let g:cpp_class_scope_highlight = 1
let g:cpp_member_variable_highlight = 1
let g:cpp_class_decl_highlight = 1
let g:cpp_posix_standard = 1
let g:cpp_experimental_simple_template_highlight = 1
let g:cpp_experimental_template_highlight = 1
let g:cpp_concepts_highlight = 1

"
" ==== clever-f ====
"
let g:clever_f_smart_case = 1

"
" ==== Yggdroot/indentLine ====
"
let g:indentLine_color_term = 239 " Vim
let g:indentLine_color_gui = '#666666' " GVim
let g:indentLine_char = '│'

"
" ==== airblade/vim-gitgutter ====
"
let g:gitgutter_sign_added = '│'
let g:gitgutter_sign_modified = '│'
let g:gitgutter_sign_removed = '│'

highlight GitGutterAdd    guifg=#487e02 ctermfg=2
highlight GitGutterChange guifg=#1b81a8 ctermfg=3
highlight GitGutterDelete guifg=#f14c4c ctermfg=1

"
" ==== machakann/vim-highlightedyank ===
"
let g:highlightedyank_highlight_duration = 200

"
" ==== voldikss/vim-floaterm ====
"
" let g:floaterm_keymap_new    = '<F7>'
" let g:floaterm_keymap_prev   = '<F8>'
" let g:floaterm_keymap_next   = '<F9>'
let g:floaterm_keymap_toggle = '<c-\>'
let g:floaterm_height = 0.8
let g:floaterm_width  = 0.7
let g:floaterm_autoclose = 2

"
" ====  RRethy/vim-illuminate ====
"
let g:Illuminate_delay = 0
let g:Illuminate_highlightUnderCursor = 1
let g:Illuminate_ftblacklist = ['nerdtree']

"
" ==== bfrg/vim-qf-diagnostics ====
"

"
" ==== neoclide/coc.nvim ====
"
"
" Install "https://github.com/junegunn/vim-plug", 
" then run :PlugInstall
"          :CocInstall coc-clangd coc-json coc-sumneko-lua coc-go
"          npm i -g bash-language-server

" Use tab for trigger completion with characters ahead and navigate
" NOTE: There's always complete item selected by default, you may want to enable
" no select by `"suggest.noselect": true` in your configuration file
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config
inoremap <silent><expr> <TAB>
      \ coc#pum#visible() ? coc#pum#next(1) :
      \ CheckBackspace() ? "\<Tab>" :
      \ coc#refresh()
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<c-h>"

" Make <cr> to accept selected completion item or notify coc.nvim to format
" <c-g>u breaks current undo, please make your own choice
inoremap <silent><expr> <cr> coc#pum#visible() ? coc#pum#confirm()
                              \: "\<c-g>u\<cr>\<c-r>=coc#on_enter()\<cr>"

function! CheckBackspace() abort
  let col = col('.') - 1
  return !col || getline('.')[col - 1]  =~# '\s'
endfunction

" Use <c-space> to trigger completion
if has('nvim')
  inoremap <silent><expr> <c-space> coc#refresh()
else
  inoremap <silent><expr> <c-@> coc#refresh()
endif

" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
nmap <silent> gt <cmd>CocDiagnostics<cr>

" GoTo code navigation
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)

" Use K to show documentation in preview window
nnoremap <silent> gh :call ShowDocumentation()<cr>

function! ShowDocumentation()
  if CocAction('hasProvider', 'hover')
    call CocActionAsync('doHover')
  else
    call feedkeys('gh', 'in')
  endif
endfunction

" Highlight the symbol and its references when holding the cursor
autocmd CursorHold * silent call CocActionAsync('highlight')

" Symbol renaming
nmap <leader>rn <Plug>(coc-rename)
" Formatting selected code
xmap <leader>fm  <Plug>(coc-format-selected)
nmap <leader>fm  <Plug>(coc-format)

augroup mygroup
  autocmd!
  " Setup formatexpr specified filetype(s)
  autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
  " Update signature help on jump placeholder
  autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end

" Applying code actions to the selected code block
" Example: `<leader>aap` for current paragraph
xmap <leader>a  <Plug>(coc-codeaction-selected)
nmap <leader>a  <Plug>(coc-codeaction-selected)

" Remap keys for applying code actions at the cursor position
nmap <leader>ac  <Plug>(coc-codeaction-cursor)
" Remap keys for apply code actions affect whole buffer
nmap <leader>as  <Plug>(coc-codeaction-source)
" Apply the most preferred quickfix action to fix diagnostic on the current line
nmap <leader>qf  <Plug>(coc-fix-current)

" Remap keys for applying refactor code actions
nmap <silent> <leader>re <Plug>(coc-codeaction-refactor)
xmap <silent> <leader>r  <Plug>(coc-codeaction-refactor-selected)
nmap <silent> <leader>r  <Plug>(coc-codeaction-refactor-selected)

" Run the Code Lens action on the current line
nmap <leader>cl  <Plug>(coc-codelens-action)

" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)

" Remap <c-f> and <c-b> to scroll float windows/popups
if has('nvim-0.4.0') || has('patch-8.2.0750')
  nnoremap <silent><nowait><expr> <c-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<c-f>"
  nnoremap <silent><nowait><expr> <c-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<c-b>"
  inoremap <silent><nowait><expr> <c-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
  inoremap <silent><nowait><expr> <c-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
  vnoremap <silent><nowait><expr> <c-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<c-f>"
  vnoremap <silent><nowait><expr> <c-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<c-b>"
endif

" Use CTRL-S for selections ranges
" Requires 'textDocument/selectionRange' support of language server
nmap <silent> <c-s> <Plug>(coc-range-select)
xmap <silent> <c-s> <Plug>(coc-range-select)

" Add `:Format` command to format current buffer
command! -nargs=0 Format :call CocActionAsync('format')

" Add `:Fold` command to fold current buffer
command! -nargs=? Fold :call     CocAction('fold', <f-args>)

" Add `:OR` command for organize imports of the current buffer
command! -nargs=0 OR   :call     CocActionAsync('runCommand', 'editor.action.organizeImport')

" Add (Neo)Vim's native statusline support
" NOTE: Please see `:h coc-status` for integrations with external plugins that
" provide custom statusline: lightline.vim, vim-airline
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}

" Mappings for CoCList
" Show all diagnostics
nnoremap <silent><nowait> <space>a  :<c-u>CocList diagnostics<cr>
" Show commands
nnoremap <silent><nowait> <space>c  :<c-u>CocList commands<cr>
" Find symbol of current document
nnoremap <silent><nowait> <space>o  :<c-u>CocList outline<cr>
" Search workspace symbols
nnoremap <silent><nowait> <space>s  :<c-u>CocList -I symbols<cr>
" Do default action for next item
nnoremap <silent><nowait> <space>j  :<c-u>CocNext<cr>
" Do default action for previous item
nnoremap <silent><nowait> <space>k  :<c-u>CocPrev<cr>
" Resume latest coc list
nnoremap <silent><nowait> <space>p  :<c-u>CocListResume<cr>
inoremap <expr> <cr> coc#pum#visible() ? coc#pum#confirm() : "\<cr>"
nnoremap <silent> <space>? :call CocActionAsync("doHover")<cr>
